#include "stdafx.h"
#include "Node.h"

#include "RigidBody.h"
#include "PhysicsSystem.h"
#include "Scene.h"
#include "GlobalAppData.h"

using namespace mscene;

Node::Node(Scene & scene, const char * name)
	: mScene(scene), mRigidBody(NULL), Type(BASE), Save(true)
{
	Position = XMFLOAT3(0.0f, 0.0f, 0.0f);
	XMStoreFloat4(&Orientation, XMQuaternionIdentity());
	Scale = XMFLOAT3(1.0f, 1.0f, 1.0f);

	setName(name);
}

Node::Node( const Node & src )
	:	Position(src.Position),
		Orientation(src.Orientation),
		Scale(src.Scale),
		IsStatic(src.IsStatic),
		mScene(src.mScene),
		Type(src.Type),
		Save(src.Save)
{
	setName(NULL);
	if(src.hasRigidBody())
		setRigidBody(src.mRigidBody->copy());
	else
		mRigidBody = NULL;
}

Node::~Node()
{
	if(hasRigidBody())
		mScene.PhysSys.removeRigidBody(*mRigidBody);
}

Node* Node::copy()
{
	return new Node(*this);
}

void Node::move(const XMFLOAT3 & vector)
{
	Position.x += vector.x;
	Position.y += vector.y;
	Position.z += vector.z;
}

void Node::rotateXY(float rotX, float rotY)
{
	XMVECTOR rot = XMQuaternionRotationRollPitchYaw(rotX / 100, rotY / 100, 0.0f);
	XMVECTOR newOr = XMQuaternionMultiply(XMLoadFloat4(&Orientation), rot);
	//newOr = XMVectorAdd(XMLoadFloat4(&Orientation), newOr);
	XMStoreFloat4(&Orientation, newOr);
}



void Node::update(float dt)
{
	if(mRigidBody != NULL)
	{
		mRigidBody = &mScene.PhysSys.findRigidBody(mRigidBodyId);
		if(mcore::GlobalAppData::Instance.IsSimulationRunning)
		{
			Position = mRigidBody->Position;
			Orientation = mRigidBody->Orientation;
		}
	}
}

void Node::updateRigidBody()
{
	mphys::RigidBodyDesc desc;
	desc.Position = Position;
	desc.Orientation = Orientation;
	desc.Scale = Scale;
	desc.Density = 0.3f;
	desc.IsStatic = IsStatic;
	mRigidBody->reset(desc);
}

float Node::rayIntersection( const mmath::Ray & ray )
{
	return std::numeric_limits<float>::infinity();
}

void Node::commitEditorChanges()
{
	if(mRigidBody != NULL)
		updateRigidBody();
}

void Node::setName( const char * name )
{
	if(name == NULL)
	{
		char buffer[8];
		_itoa(mCurrentDefaultNum++, buffer, 10);
		strcpy_s<NAME_MAX_SIZE>(mName, "DefName");
		strcat_s<NAME_MAX_SIZE>(mName, buffer);
	}
	else
	{
		strcpy_s<NAME_MAX_SIZE>(mName, name);
	}
}

const char * Node::getName() const
{
	return mName;
}

void Node::setRigidBody(mphys::RigidBody & rb)
{
	mRigidBody = &rb;
	mRigidBodyId = rb.Id;
}

mphys::RigidBody & Node::getRigidBody()
{
	assert(mRigidBody != NULL);
	return *mRigidBody;
}

int Node::mCurrentDefaultNum = 0;

